using System.Linq.Expressions;
using Blog2025.Domain.Filters;

namespace Blog2025.Infrastructure.Filters;

public class GenericFilter<T>:IFilter<T>
{
    public IEnumerable<T> Filter(IEnumerable<T> data, Dictionary<string ,object> filters)
    {
        var filteredData=data.AsQueryable();
        foreach (var filter in filters)
        {
            var field=filter.Key;
            var condition=filter.Value;
            if(condition is Dictionary<string,object> compositeCondition)
            {
                foreach (var op in compositeCondition)
                {
                    filteredData=Apply(filteredData,field,op.Key,op.Value);
                }
            }
            else
            {
                filteredData=Apply(filteredData,field,"eq",condition);
            }
        }
        return filteredData.ToList();
    }

    // 定义一个私有的
    private IQueryable<T> Apply(IQueryable<T> data,string field,string op,object value)
    {
        // IQueryable<T> data：这是要进行过滤的数据集合，类型是 IQueryable<T>，表示一个可查询的泛型集合。
        // string field：表示要过滤的字段名称，例如 "Name" 或 "Age"。
        // string op：表示操作符，例如 "eq" 表示等于。
        // object value：表示要比较的值，例如 5 或 "John"。
        // 返回值：返回一个经过过滤的 IQueryable<T> 集合。
        var parameter=Expression.Parameter(typeof(T),"x");
        // 这里创建了一个参数表达式，表示 data 集合中每个元素的引用。
        // typeof(T) 表示集合中元素的类型。
        // "x" 是参数的名称，用于在表达式中引用集合中的每个元素。
        var member=Expression.PropertyOrField(parameter,field);
        // 这里创建了一个成员访问表达式，用于访问 parameter 参数的某个属性或字段。
        // field 是属性或字段的名称，例如 "Name" 或 "Age"。
        // 这个表达式的作用是表示 x.Name 或 x.Age。
        var constant=Expression.Constant(value);
        // 这里创建了一个常量表达式，表示要比较的值。
        // value 是传入的比较值，例如 5 或 "John"。
        // 这个表达式的作用是表示一个固定的值。
        Expression comparison;

        switch (op)
        {
            case "eq":
            comparison=Expression.Equal(member,constant);
            break;
            default:
            throw new ArgumentException($"sdf");
        }
        var lambda=Expression.Lambda<Func<T,bool>>(comparison,parameter);
        // 这里将比较表达式 comparison 封装成一个 Lambda 表达式。
        // Func<T, bool> 表示这个 Lambda 表达式是一个函数，输入是 T 类型的对象，输出是 bool 类型的值。
        // comparison 是比较逻辑，parameter 是输入参数。
        // 例如，如果 field 是 "Name"，op 是 "eq"，value 是 "John"，那么这个 Lambda 表达式就相当于 x => x.Name == "John"。
        return data.Where(lambda);
        // 这里使用 IQueryable<T>.Where 方法将 Lambda 表达式应用到数据集合 data 上。
        // lambda 是过滤条件，data.Where(lambda) 表示从 data 中筛选出满足条件的元素。
        // 返回值是一个新的 IQueryable<T> 集合，其中只包含满足过滤条件的元素。
    }
}